<template>
    <div id="mineSweeper" class="no-select">
        <MeowHeader :header-obj="headerObj"/>
        <div class="info">
            <div class="time">
                <span class="iconfont icon-shijian"> {{getTime()}}</span>
            </div>
            <div class="new" @click="init">
                <span class="iconfont icon-game-renew"/>
            </div>
            <div class="min">
                <span>最佳 {{getMinTime()}}</span>
            </div>
        </div>
        <div class="game-times">
            <span>成功：{{result.successTimes}}次</span>
            <span>失败：{{result.failTimes}}次</span>
        </div>
        <mu-flex class="game-content no-select" justify-content="between" align-items="center" direction="column">
            <mu-flex class="row" v-for="(row,index) in arr" :key="index" justify-content="between">
                <!-- unit-box 设置每个格子的初始背景色 -->
                <!-- :title1="unit.text===-1 ? '炸弹' : '安全'" :title2="unit.state+','+unit.text" -->
                <div v-for="(unit,index2) in row" :key="index2"
                     class="unit-box" :class="getUnitClass(unit)" :position="unit.position"
                     @click="singleClick(unit)" @contextmenu.prevent="rightClick(unit)"
                     @touchstart="touchstart()" @touchmove="touchmove()" @touchend="touchend()">
                    <!-- 未翻开 -->
                    <template v-if="unit.state===0">
                        <span v-if="unit.text===-2" class="iconfont icon-zhadan2"/>
                        <span v-else-if="unit.text===-3" class="iconfont icon-zhadan"/>
                        <span v-else/>
                    </template>
                    <!-- 已翻开 -->
                    <template v-else-if="unit.state===1">
                        <span v-if="unit.text===-1" class="iconfont icon-zhadan2"/>
                        <span v-else-if="unit.text===-2" class="iconfont icon-baozha2"/>
                        <span v-else class="text" :class="`t${unit.text}`">{{unit.text}}</span>
                    </template>
                    <!-- 旗帜标记 -->
                    <template v-else-if="unit.state===2">
                        <span class="iconfont icon-qizhi"/>
                    </template>
                    <!-- 问号标记 -->
                    <template v-else-if="unit.state===3">
                        <span class="iconfont icon-wenhao"/>
                    </template>
                </div>
            </mu-flex>
        </mu-flex>
        <mu-dialog width="360" :open.sync="result.gameOverDialog">
            <span slot="title" class="no-select">GAME OVER</span>
            <span class="no-select">胜败乃兵家常事，大侠请重新来过！</span>
            <mu-button slot="actions" flat color="success" @click="closeGameOverDialog(1)">新游戏</mu-button>
            <mu-button slot="actions" flat color="primary" @click="closeGameOverDialog(2)">关闭</mu-button>
        </mu-dialog>
        <mu-dialog width="360" :open.sync="result.gameSuccessDialog">
            <span slot="title" class="no-select">恭喜通关</span>
            <span class="no-select">恭喜通关，耗时{{getTime()}}</span>
            <mu-button slot="actions" flat color="success" @click="closeSuccessDialog(1)">新游戏</mu-button>
            <mu-button slot="actions" flat color="primary" @click="closeSuccessDialog(2)">关闭</mu-button>
        </mu-dialog>
        <div class="game-introduce">
            <!-- <p>找出所有的地雷吧！</p> -->
            <!-- <p>网页端单击翻开，右击标记</p> -->
            <!-- <p>手机端点击翻开，长按标记</p> -->
            <p>点击翻开，长按或双击标记。你能找出所有的地雷么？</p>
            <p>
                <span v-if="mouse.palmRejection">双击防误触开启 </span>
                <span v-else>双击防误触关闭 </span>
                <el-switch v-model="mouse.palmRejection"/>
            </p>
        </div>
    </div>
</template>

<script>
    import MeowHeader from "@/components/MeowHeader";
    import util from "@/assets/js/util";
    import $ from 'jquery';

    export default {
        name: "mineSweeper",
        components: {MeowHeader},
        data() {
            return {
                headerObj: {
                    title: "扫雷",
                },
                row: 9,//行
                line: 9,//列
                arr: [],//地雷阵数组
                time: '00:00',//用时
                total: 10,//炸弹总数
                currentUnit: {},
                // 游戏结果相关参数
                result:{
                    // 判断游戏结果
                    gameOverFlag: false,
                    gameSuccessFlag: false,
                    gameOverDialog: false,
                    gameSuccessDialog: false,
                    // 记录游戏时间
                    timeOut: 0,
                    timeOutEvent: 0,
                    minTimeCookieName: 'mineSweeper_min_time',
                    // 记录游戏次数
                    successTimes:0,
                    failTimes:0,
                    successTimesName: 'mineSweeper_success_times',
                    failTimesName: 'mineSweeper_fail_times',
                },
                // 鼠标操作相关参数
                mouse: {
                    clickEvent: 0,
                    isDoubleClick: false,
                    timestamp: 0,
                    lastUnit: '',
                    palmRejection: false,
                },
                // 触摸相关参数
                touch: {
                    startX: '',
                    startY: '',
                    endX: '',
                    endY: '',
                    slideFlag: false,
                    longPressEvent: 0,
                    fingerClickEvent: 0,
                    lastClickPosition: '',
                    timestamp: 0,
                },
            }
        },
        mounted() {
            let _this = this,
                type = _this.$route.query.type;
            // 禁止选择和复制
            $('html').addClass('no-select');
            // 禁止缩放
            $('head').after('<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">');
            switch (type) {
                case 'normal':
                    _this.row = 16;
                    _this.total = 25;
                    _this.result.minTimeCookieName = 'mineSweeper_min_time_normal';
                    _this.result.successTimesName = 'mineSweeper_success_times_normal';
                    _this.result.failTimesName = 'mineSweeper_fail_times_normal';
                    break;
                case 'hard':
                    _this.row = 30;
                    _this.total = 52;
                    _this.result.minTimeCookieName = 'mineSweeper_min_time_hard';
                    _this.result.successTimesName = 'mineSweeper_success_times_hard';
                    _this.result.failTimesName = 'mineSweeper_fail_times_hard';
                    break;
                default:
                    _this.row = 9;
                    _this.line = 9;
                    _this.total = 10;
            }
            _this.init();
            _this.result.successTimes = sessionStorage.getItem(_this.result.successTimesName) || 0;
            _this.result.failTimes =  sessionStorage.getItem(_this.result.failTimesName) || 0;
        },
        methods: {
            //
            getUnitClass(unit) {
                if (unit.state === 1) {
                    return 'blank';
                }
                // 插旗子或标问号的地雷
                if (unit.state > 1 && unit.text < 0) {
                    if (this.result.gameSuccessFlag) {
                        return 'found';
                    }
                    if (this.result.gameOverFlag) {
                        return 'expose';
                    }
                }
            },
            // 游戏初始化
            init: function () {
                let _this = this;

                _this.arr = [];
                _this.result.gameOverFlag = false;
                _this.result.gameSuccessFlag = false;
                _this.mouse = {
                    clickEvent: 0,
                    isDoubleClick: false,
                    timestamp: 0,
                    lastUnit: '',
                    palmRejection: _this.mouse.palmRejection,
                };
                _this.touch = {
                    startX: '',
                    startY: '',
                    endX: '',
                    endY: '',
                    slideFlag: false,
                    longPressEvent: 0,
                    fingerClickEvent: 0,
                    lastClickPosition: '',
                    timestamp: 0,
                };

                // 初始化空白数组
                for (let i = 1; i <= _this.row; i++) {
                    let _line = [];
                    for (let j = 1; j <= _this.line; j++) {
                        _line.push({
                            position: i + ',' + j,
                            text: '',
                            state: 0,
                        });
                    }
                    _this.arr.push(_line);
                }
                // 初始化地雷数组
                for (let i = 0; i < _this.total; i++) {
                    let blankUnits = _this.getBlankUnits(),
                        num = util.randomNum(blankUnits.length - 1);
                    _this.getCurrentUnit(blankUnits[num].position);
                    _this.currentUnit.text = -1;
                }
                // 初始化地雷周边数字
                _this.arr.map(row => {
                    row.map(unit => {
                        if (unit.text !== -1) {
                            unit.text = _this.getMiceCount(unit.position);
                        }
                    })
                });
                // 清除定时器
                clearInterval(_this.result.timeOutEvent);
                _this.result.timeOutEvent = null;
                // 重新开始计时
                _this.result.timeOut = 0;
                _this.result.timeOutEvent = setInterval(() => {
                    _this.result.timeOut++;
                }, 1000);
            },
            // 得到某个坐标位置的格子元素
            getCurrentUnit(position) {
                let _this = this,
                    flag = false;
                _this.arr.map(row => {
                    row.map(unit => {
                        if (unit.position === position) {
                            _this.currentUnit = unit;
                            flag = true;
                        }
                    })
                });
                if (!flag) {
                    _this.currentUnit = null;
                }
            },
            // 得到所有的空格子
            getBlankUnits() {
                let _this = this,
                    list = [];
                _this.arr.map(row => {
                    row.map(unit => {
                        if (unit.text === '') {
                            list.push({
                                position: unit.position + '',
                            })
                        }
                    })
                });
                return list;
            },
            // 得到周围的地雷数目
            getMiceCount(position) {
                let _this = this,
                    count = 0,
                    index = position.split(','),
                    i = parseInt(index[0]),
                    j = parseInt(index[1]),
                    around = [
                        (i - 1) + ',' + (j - 1), (i - 1) + ',' + j, (i - 1) + ',' + (j + 1),
                        i + ',' + (j - 1), i + ',' + (j + 1),
                        (i + 1) + ',' + (j - 1), (i + 1) + ',' + j, (i + 1) + ',' + (j + 1),
                    ];
                for (let k = 0; k < around.length; k++) {
                    _this.getCurrentUnit(around[k]);
                    if (_this.currentUnit !== null) {
                        if (_this.currentUnit.text === -1) {
                            count++;
                        }
                    }
                }
                return count === 0 ? '' : count;
            },
            // 翻开一个空白的格子
            overturnBlank(position) {
                let _this = this,
                    index = position.split(','),
                    i = parseInt(index[0]),
                    j = parseInt(index[1]),
                    around = [
                        (i - 1) + ',' + (j - 1), (i - 1) + ',' + j, (i - 1) + ',' + (j + 1),
                        i + ',' + (j - 1), i + ',' + (j + 1),
                        (i + 1) + ',' + (j - 1), (i + 1) + ',' + j, (i + 1) + ',' + (j + 1),
                    ];
                for (let k = 0; k < around.length; k++) {
                    _this.getCurrentUnit(around[k]);
                    if (_this.currentUnit != null) {
                        if (_this.currentUnit.state === 0) {
                            if (_this.currentUnit.text > -1) {
                                _this.currentUnit.state = 1;
                            }
                            if (_this.currentUnit.text === '') {
                                _this.overturnBlank(_this.currentUnit.position);
                            }
                        }
                    }
                }
            },
            // 单击
            singleClick(unit) {
                let _this = this,
                    doubleClickTime = 250, //双击判断时间
                    diff = new Date().getTime() - _this.mouse.timestamp;
                _this.mouse.isDoubleClick = false;
                console.log('鼠标单击事件');
                if (util.isMobile()) {
                    // 判断手指单击还是双击
                    let nearbyFlag = false;
                    if (_this.mouse.lastUnit !== '') {
                        if (_this.mouse.palmRejection) {
                            // 开启防误触
                            let currPos = unit.position.split(','),
                                lastPos = JSON.parse(_this.mouse.lastUnit).position.split(',');
                            if (Math.abs(currPos[0] - lastPos[0]) <= 1 && Math.abs(currPos[1] - lastPos[1]) <= 1) {
                                // 连续两次点击发生时，第二次点击到了临近的格子，不算做两次单击事件
                                // 而算作第一个格子的双击事件
                                nearbyFlag = true;
                            }
                        } else {
                            if (_this.mouse.lastUnit === JSON.stringify(unit)) {
                                // 关闭防误触，只有连续点击两个相同的格子才算一次双击事件，否则视为两次单击事件
                                nearbyFlag = true;
                            }
                        }
                    } else {
                        nearbyFlag = true;
                    }
                    if (!nearbyFlag) {
                        // 单击
                        util.vibrate(10);
                        console.log('手指单击事件other');
                        _this.overturnUnit(unit);
                    } else {
                        console.log('手指点击，距离上一次的时间' + diff);
                        if (diff < doubleClickTime) {
                            console.log('手指双击事件');
                            util.vibrate(10);
                            _this.getCurrentUnit(JSON.parse(_this.mouse.lastUnit).position);
                            _this.markUnit(_this.currentUnit);
                            _this.mouse.isDoubleClick = true;
                        }
                        _this.mouse.lastUnit = JSON.stringify(unit);
                    }
                    _this.mouse.clickEvent = setTimeout(() => {
                        // 一段时间内没有再次点击，执行上一次的点击事件
                        if (!_this.mouse.isDoubleClick) {
                            util.vibrate(10);
                            console.log('手指单击事件[timeout触发]');
                            _this.overturnUnit(unit);
                            _this.mouse.timestamp = 0;
                            _this.mouse.lastUnit = '';
                        }
                    }, doubleClickTime);
                    if (_this.mouse.isDoubleClick) {
                        // 执行了一次双击事件
                        _this.mouse.lastUnit = '';
                        _this.mouse.timestamp = 0;
                        clearTimeout(_this.mouse.clickEvent);
                        _this.mouse.clickEvent = null;
                    } else {
                        _this.mouse.timestamp = new Date().getTime();
                    }
                } else {
                    console.log('鼠标单击里调用的翻转');
                    this.overturnUnit(unit);
                }
            },
            // 右击
            rightClick(unit) {
                console.log('鼠标右击事件');
                if (!util.isMobile()) {
                    console.log('鼠标右击里调用的标记');
                    this.markUnit(unit);
                }
            },
            // 翻开一个格子
            overturnUnit(unit) {
                console.log('【翻转】' + JSON.stringify(unit));
                if (this.checkOver()) {
                    return;
                }
                unit.state = 1;
                if (unit.text === '') {
                    this.overturnBlank(unit.position);
                }
                if (unit.text === -1) {
                    this.checkFail(unit);
                }
                this.checkSuccess();
            },
            // 标记一个格子
            markUnit(unit) {
                console.log('【标记】' + JSON.stringify(unit));
                if (this.checkOver()) {
                    return;
                }
                switch (unit.state) {
                    case 0:
                        unit.state = 2;
                        break;
                    case 2:
                        unit.state = 3;
                        break;
                    case 3:
                        unit.state = 0;
                }
            },
            // 判断游戏是否结束，包含失败或者成功
            checkOver() {
                if (this.result.gameSuccessFlag) {
                    this.result.gameSuccessDialog = true;
                    return true;
                }
                if (this.result.gameOverFlag) {
                    this.result.gameOverDialog = true;
                    return true;
                }
                return false;
            },
            // 判断游戏是否失败
            checkFail(unit) {
                unit.text = -2;
                this.arr.map(row => {
                    row.map(_unit => {
                        if (_unit.text === -1) {
                            _unit.text = -2;
                        }
                    })
                });
                this.result.gameOverFlag = true;
                this.result.gameOverDialog = true;
                //清除定时器
                clearInterval(this.result.timeOutEvent);
                this.result.timeOutEvent = null;
                // 更新失败次数
                this.result.failTimes++;
                sessionStorage.setItem(this.result.failTimesName, this.result.failTimes);
            },
            // 判断游戏是否通关
            checkSuccess() {
                this.result.gameSuccessFlag = true;
                this.arr.map(row => {
                    row.map(unit => {
                        if (unit.state !== 1 && unit.text !== -1) {
                            this.result.gameSuccessFlag = false;
                        }
                    })
                });
                if (this.result.gameSuccessFlag) {
                    // 通关
                    this.result.gameSuccessDialog = true;
                    //清除定时器
                    clearInterval(this.result.timeOutEvent);
                    this.result.timeOutEvent = null;
                    if (this.getMinTime() === '00:00' || this.getTime() < this.getMinTime()) {
                        this.$cookies.set(this.result.minTimeCookieName, this.getTime());
                    }
                    this.arr.map(row => {
                        row.map(unit => {
                            if (unit.text === -1) {
                                unit.text = -3;
                            }
                        })
                    });
                    this.result.gameOverFlag = true;
                    // 更新成功次数
                    this.result.successTimes++;
                    sessionStorage.setItem(this.result.successTimesName, this.result.successTimes);
                }
            },
            // 关闭游戏失败的弹框
            closeGameOverDialog(type) {
                if (type === 1) {
                    this.init();
                }
                this.result.gameOverDialog = false;
            },
            // 关闭游戏通关的弹框
            closeSuccessDialog(type) {
                if (type === 1) {
                    this.init();
                }
                this.result.gameSuccessDialog = false;
            },
            // 获取游戏进行时间
            getTime() {
                let min = Math.floor(this.result.timeOut / 60),
                    sec = this.result.timeOut - min * 60;
                if (min < 10) {
                    min = '0' + min;
                }
                if (sec < 10) {
                    sec = '0' + sec;
                }
                return min + ":" + sec;
            },
            // 获取历史最佳成绩
            getMinTime() {
                let min = this.$cookies.get(this.result.minTimeCookieName);
                if (min !== null) {
                    return min;
                }
                return '00:00';
            },
            // 监听触摸屏幕
            touchstart: function () {
                // 阻止默认事件（长按的时候出现复制）
                // event.preventDefault();
                let _this = this;
                _this.touch.endY = '';
                _this.touch.endY = '';
                _this.touch.startX = event.changedTouches[0].pageX;
                _this.touch.startY = event.changedTouches[0].pageY;
                let position = $(event.target).attr('position');
                if (position === undefined) {
                    position = $(event.target).parent().attr('position');
                }
                // let diff = new Date().getTime() - _this.touch.timestamp;
                // if (diff<500){
                //     // 500ms内再次点击算作双击
                //     if (position===_this.touch.lastClickPosition){
                //         // 清除单击计时器
                //         clearTimeout(_this.touch.fingerClickEvent);
                //         _this.touch.fingerClickEvent = null;
                //
                //         console.log('手指双击'+position);
                //         _this.getCurrentUnit(position);
                //         _this.markUnit(_this.currentUnit);
                //         util.vibrate(10);
                //     }
                //     _this.touch.timestamp = 0;
                //     return;
                // }
                _this.touch.timestamp = new Date().getTime();
                _this.touch.lastClickPosition = position;
                _this.touch.slideFlag = false;
                _this.touch.longPressEvent = setTimeout(() => {
                    // 长按
                    console.log('手指长按' + position);
                    _this.getCurrentUnit(position);
                    _this.markUnit(_this.currentUnit);
                    // util.vibrate(10);// 10ms微振动，不主动调用震动，使用默认触发的震动
                }, 500);
            },
            // 监听手指移动
            touchmove() {
                let _this = this;
                // event.preventDefault();
                _this.touch.endX = event.changedTouches[0].pageX;
                _this.touch.endY = event.changedTouches[0].pageY;
                _this.touch.slideFlag = true;
                clearTimeout(_this.touch.longPressEvent);
                _this.touch.longPressEvent = null;
            },
            // 监听手指释放
            touchend() {
                let _this = this;
                // event.preventDefault();
                if (_this.touch.endY === '' || _this.touch.endY === '') {
                    _this.touch.slideFlag = false;
                } else {
                    let xLength = _this.touch.endX - _this.touch.startX,
                        yLength = _this.touch.endY - _this.touch.startY;
                    if (Math.abs(xLength) < 10 && Math.abs(yLength) < 10) {
                        _this.touch.slideFlag = false;
                    }
                }
                if (!_this.touch.slideFlag) {
                    let diff = new Date().getTime() - _this.touch.timestamp;
                    if (diff < 500) {
                        // 清除长按计时器
                        clearTimeout(_this.touch.longPressEvent);
                        _this.touch.longPressEvent = null;
                        // let position = $(event.target).attr('position');
                        // if (position === undefined) {
                        //     position = $(event.target).parent().attr('position');
                        // }
                        // 500ms内没有再次点击算作一次单击
                        // _this.touch.fingerClickEvent = setTimeout(()=>{
                        //     console.log('手指点击'+position);
                        //     _this.getCurrentUnit(position);
                        //     _this.overturnUnit(_this.currentUnit);
                        //     util.vibrate(10);
                        // },150);
                    }
                }
            }
        }
    }
</script>

<style scoped lang="less">
    #mineSweeper {
        .info {
            display: flex;
            justify-content: center;
            margin-top: 30px;
            line-height: 30px;
            font-size: 18px;

            .time {
                color: #bcbcbc;
            }

            .new {
                color: #2196f3;
                margin: 0 20px;
            }

            .min {
                color: #ff0000;
            }
        }

        .game-content {
            margin: auto;
            background-color: #ebeef5;
            border-radius: 5px;
            width: 370px;
            padding: 5px;
            box-sizing: border-box;

            .row {
                .unit-box {
                    width: 40px;
                    height: 40px;
                    font-size: 30px;
                    box-sizing: border-box;
                    border: 2pX solid #fff;
                    border-right-color: #808080;
                    border-bottom-color: #808080;
                    background-color: #bcbcbc;
                    color: #000;
                    display: flex;
                    justify-content: center; /* 水平居中 */
                    align-items: center; /* 垂直居中 */
                    position: relative;

                    .iconfont:before {
                        font-size: 30px;
                    }

                    .icon-zhadan:before {
                        color: #000;
                    }

                    .icon-zhadan2:before {
                        color: #ff0000;
                    }

                    .icon-baozha2:before {
                        color: #ff0000;
                        font-size: 40px;
                    }

                    .icon-qizhi:before {
                        color: #ff0000;
                    }

                    .icon-wenhao:before {
                        color: #2196f3;
                        font-size: 26px;
                    }

                    .t1 {
                        color: #00f;
                    }

                    .t2 {
                        color: #008;
                    }

                    .t3 {
                        color: #f59565;
                    }

                    .t4 {
                        color: #f07f61;
                    }

                    .t5 {
                        color: #f65d3b;
                    }

                    .t6 {
                        color: #edce71;
                    }

                    .t7 {
                        color: #eece5f;
                    }

                    .t8 {
                        color: #f2b179;
                    }
                }

                .blank {
                    background-color: #ebeef5;
                }

                .found {
                    span {
                        background: url('~@/assets/img/baozha.png') center center no-repeat;
                        background-size: 100%;
                    }
                }

                .expose {
                    span {
                        background: url('~@/assets/img/baozha2.png') center center no-repeat;
                        background-size: 100%;
                    }

                    span.iconfont:before {
                        color: #000000;
                    }
                }
            }
        }

        // 介绍
        .game-introduce {
            margin-top: 30px;
            font-size: 14px;

            p {
                margin: 5px 0;
            }
        }

        // 介绍
        .game-times {
            margin: 10px 0;
            font-size: 14px;
            color: #808080;
            span {
                margin: 0 5Px;
            }
        }
    }
</style>
